package me.xhy.java.springboot3.r2dbc.s05one2one;

import me.xhy.java.springboot3.r2dbc.s05one2one.s051entity.S0511Author;
import me.xhy.java.springboot3.r2dbc.s05one2one.s051entity.S0512Book;
import me.xhy.java.springboot3.r2dbc.s05one2one.s051entity.S0513Book;
import me.xhy.java.springboot3.r2dbc.s05one2one.s051entity.S0514AuthorRelBook;
import me.xhy.java.springboot3.r2dbc.s05one2one.s052repository.S0521BookRepository;
import me.xhy.java.springboot3.r2dbc.s05one2one.s052repository.S0522BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.r2dbc.core.DatabaseClient;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@SpringBootTest(classes = S053Application.class)
public class S054Test {

  @Autowired
  S0521BookRepository s0521bookRepository;

  @Autowired
  S0522BookRepository s0522bookRepository;

  @Autowired
  DatabaseClient databaseClient;

  @Test
  void testSingleBook() throws Exception {
    s0521bookRepository.findAll().subscribe(System.out::println);

    TimeUnit.SECONDS.sleep(10);
  }

  @Test
  void testBookRelAuthor() throws Exception {
    s0522bookRepository.findBookRelAuthor(1L).subscribe(System.out::println);

    TimeUnit.SECONDS.sleep(10);
  }

  @Test
  void testBookRelAuthor2() throws Exception {
    databaseClient
        .sql("select a.*, b.name from t_book a left join t_author b on a.author_id = b.id where b.id = ?")
        .bind(0, 1L)
        .fetch()
        .all()
        .map(row -> {
          S0513Book s0513Book = new S0513Book();
          S0511Author s0511Author = new S0511Author();

          s0511Author.setId(Long.valueOf(row.get("author_id").toString()));
          s0511Author.setName(row.get("name").toString());

          s0513Book.setId(Long.valueOf(row.get("id").toString()));
          s0513Book.setTitle(row.get("title").toString());
          s0513Book.setAuthorId(s0511Author.getId());
          s0513Book.setPublisherTime(((LocalDateTime) row.get("publish_time")).toInstant(ZoneOffset.UTC)); // 查询出来是 java.time.LocalDateTime
          s0513Book.setAuthor(s0511Author);

          return s0513Book;
        }).subscribe(System.out::println);

    TimeUnit.SECONDS.sleep(10);
  }

  /*
  s0522bookRepository 返回的是 S0513Book 对象，并且当前环境中自定义了一个 Converter 是针对返回值 S0513Book 的
  （只要返回值是 S0513Book ，就会应用 S055BookConverter）
  在使用类似 s0522bookRepository.findAll 这种单表查询的时候，就会产生bug
   */
  @Test
  void testExceptionAfterConverter() throws Exception {
    s0522bookRepository.findAll().subscribe(System.out::println);

    TimeUnit.SECONDS.sleep(10);
  }

  @Test
  void testAuthorRelBookRel() throws Exception {
    databaseClient
        .sql("select a.*, b.title, b.author_id, b.publish_time, b.id as book_id from t_author a left join t_book b on a.id = b.author_id order by a.id")
        .fetch()
        .all()
        .bufferUntilChanged(row -> Long.parseLong(row.get("id").toString()))
        .map(list -> {
          Map<String, Object> stringObjectMap = list.get(0);
          S0514AuthorRelBook authorRelBook = new S0514AuthorRelBook();
          authorRelBook.setId(Long.valueOf(stringObjectMap.get("id").toString()));
          authorRelBook.setName(stringObjectMap.get("name").toString());

          List<S0512Book> bookList = list.stream().map(item -> {
            S0512Book book = new S0512Book();
            book.setId(Long.valueOf(item.get("book_id").toString()));
            book.setTitle(item.get("title").toString());
            book.setAuthorId(Long.parseLong(item.get("author_id").toString()));
            book.setPublishTime(((LocalDateTime) item.get("publish_time")).toInstant(ZoneOffset.UTC));

            return book;
          }).collect(Collectors.toList());

          authorRelBook.setBookList(bookList);

          return authorRelBook;

        })
        .subscribe(System.out::println);

    TimeUnit.SECONDS.sleep(10);
  }



}
